]> dgit.raspbian.org Git - pcre2.git/commitdiff
Backport of pcre2-10.48-Fix-JIT-match-context-reuse.patch
authorNicholas Wilson <nicholas@nicholaswilson.me.uk>
Sat, 8 Aug 2026 18:17:36 +0000 (19:17 +0100)
committerMatthew Vernon <matthew@debian.org>
Tue, 1 Sep 2026 10:43:48 +0000 (11:43 +0100)
Cherry-pick of 1dcd0cf42a6a7cb62cc9a7c024196733abcfda95 and 1cad831209af67d24298c301a74c615d3a6d57eb

Fix leak & stale PCRE2_MD_COPIED_SUBJECT if pcre2_jit_match used with existing match context (#937)

The problem is not that pcre2_jit_match() needs to add support for PCRE2_COPY_MATCHED_SUBJECT. Instead, if the passed-in context somehow contains a previously-copied subject (by non-JIT matcher using a global or cached subject) then it will be leaked, and worse, incorrectly free'd later.

pcre2test: honor no_jit when used with jitfast (#946)

`pcre2_jit_match()` ignores the PCRE2_NO_JIT option, so teach pcre2test
to avoid calling it if the subject modifier that sets that option is
used together with the option to call it directly.

While at it, make jitverify more reliable and add a unittest to validate
that PCRE2_NO_JIT is ignored in the fast JIt path.

(cherry picked from commit e5b9232fc4cd6a0df312ae25568e72cd337cafa2)

src/pcre2_jit_match.c
src/pcre2test.c
testdata/testinput17
testdata/testoutput17

index 8867f768df15c294b741a97cd51de6f9f4b768bd..23a2d405f30da664080e9ea3a03256ebc1c93a20 100644 (file)
@@ -126,6 +126,16 @@ else if ((options & PCRE2_PARTIAL_SOFT) != 0)
 if (functions == NULL || functions->executable_funcs[index] == NULL)
   return PCRE2_ERROR_JIT_BADOPTION;
 
+/* If the match data block was previously used with PCRE2_COPY_MATCHED_SUBJECT,
+free the memory that was obtained. */
+
+if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
+  {
+  match_data->memctl.free((void *)match_data->subject,
+    match_data->memctl.memory_data);
+  match_data->flags &= ~PCRE2_MD_COPIED_SUBJECT;
+  }
+
 /* Sanity checks should be handled by pcre2_match. */
 arguments.str = subject + start_offset;
 arguments.begin = subject;
index a6696bc9aae3696b8c7d42f1b841a272c1789f67..199bdff9bc63b55c7f31cff43d964537ec481ce7 100644 (file)
@@ -6421,7 +6421,8 @@ for (;;)
       PTR(dat_context), dfa_workspace, DFA_WS_DIMENSION);
     }
 
-  else if ((pat_patctl.control & CTL_JITFAST) != 0)
+  else if ((pat_patctl.control & CTL_JITFAST) != 0 &&
+           (dat_datctl.options & PCRE2_NO_JIT) == 0)
     PCRE2_JIT_MATCH(capcount, compiled_code, pp, ulen, dat_datctl.offset,
       dat_datctl.options, match_data, PTR(dat_context));
 
@@ -8021,7 +8022,8 @@ if (dat_datctl.replacement[0] != 0)
 
   if (emoption != 0)
     {
-    if ((pat_patctl.control & CTL_JITFAST) != 0)
+    if ((pat_patctl.control & CTL_JITFAST) != 0 &&
+        (dat_datctl.options & PCRE2_NO_JIT) == 0)
       {
       PCRE2_JIT_MATCH(rc, compiled_code, pp, arg_ulen, dat_datctl.offset,
         dat_datctl.options, match_data, use_dat_context);
@@ -8240,7 +8242,8 @@ for (gmatched = 0;; gmatched++)
         }
       }
 
-    else if ((pat_patctl.control & CTL_JITFAST) != 0)
+    else if ((pat_patctl.control & CTL_JITFAST) != 0 &&
+             (dat_datctl.options & PCRE2_NO_JIT) == 0)
       {
       start_time = clock();
       for (i = 0; i < timeitm; i++)
@@ -8337,7 +8340,8 @@ for (gmatched = 0;; gmatched++)
       }
     else
       {
-      if ((pat_patctl.control & CTL_JITFAST) != 0)
+      if ((pat_patctl.control & CTL_JITFAST) != 0 &&
+          (dat_datctl.options & PCRE2_NO_JIT) == 0)
         PCRE2_JIT_MATCH(capcount, compiled_code, pp, arg_ulen, dat_datctl.offset,
           dat_datctl.options | g_notempty, match_data, use_dat_context);
       else
@@ -8385,20 +8389,29 @@ for (gmatched = 0;; gmatched++)
     /* If PCRE2_COPY_MATCHED_SUBJECT was set, check that things are as they
     should be, but not for fast JIT, where it isn't supported. */
 
-    if ((dat_datctl.options & PCRE2_COPY_MATCHED_SUBJECT) != 0 &&
-        (pat_patctl.control & CTL_JITFAST) == 0)
+    if ((dat_datctl.options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
       {
-      if ((FLD(match_data, flags) & PCRE2_MD_COPIED_SUBJECT) == 0)
-        fprintf(outfile,
-          "** PCRE2 error: flag not set after copy_matched_subject\n");
+      if ((pat_patctl.control & CTL_JITFAST) != 0 &&
+          (dat_datctl.options & PCRE2_NO_JIT) == 0)
+        {
+        if ((FLD(match_data, flags) & PCRE2_MD_COPIED_SUBJECT) != 0)
+          fprintf(outfile,
+            "** PCRE2 error: flag set after unsupported copy_matched_subject\n");
+        }
+      else
+        {
+        if ((FLD(match_data, flags) & PCRE2_MD_COPIED_SUBJECT) == 0)
+          fprintf(outfile,
+            "** PCRE2 error: flag not set after copy_matched_subject\n");
 
-      if (CASTFLD(const void *, match_data, subject) == pp)
-        fprintf(outfile,
-          "** PCRE2 error: copy_matched_subject has not copied\n");
+        if (CASTFLD(const void *, match_data, subject) == pp)
+          fprintf(outfile,
+            "** PCRE2 error: copy_matched_subject has not copied\n");
 
-      if (memcmp(CASTFLD(const void *, match_data, subject), pp, ulen) != 0)
-        fprintf(outfile,
-          "** PCRE2 error: copy_matched_subject mismatch\n");
+        if (memcmp(CASTFLD(const void *, match_data, subject), pp, ulen) != 0)
+          fprintf(outfile,
+            "** PCRE2 error: copy_matched_subject mismatch\n");
+        }
       }
 
     /* If this is not the first time round a global loop, check that the
index 7dd2d8ea906df70e1d930591010032f386e6396e..b979a63470544bd67200452cc21e484157abe4ba 100644 (file)
     
 /abc/jitfast
     abc
+    abc\=copy_matched_subject
     abc\=no_jit 
-    
+
+/abc/jitfast
+    abc\=copy_matched_subject,no_jit
+    abc
+
 # ---- 
 
 /[aC]/mg,firstline,newline=lf
index 95f3959714cf35466b907dd5bf6d8d4c0a8a6342..2f1c4e98fd8cf7bbf41a75f1d77c59aac0d088d3 100644 (file)
@@ -538,10 +538,18 @@ Failed: error -47: match limit exceeded
     
 /abc/jitfast
     abc
+ 0: abc (JIT)
+    abc\=copy_matched_subject
  0: abc (JIT)
     abc\=no_jit 
  0: abc (JIT)
-    
+
+/abc/jitfast
+    abc\=copy_matched_subject,no_jit
+ 0: abc (JIT)
+    abc
+ 0: abc (JIT)
+
 # ---- 
 
 /[aC]/mg,firstline,newline=lf